{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# python notebook for Make Your Own Neural Network\n",
    "# code for a 3-layer neural network, and code for learning the MNIST dataset\n",
    "# this version asks the network what the image should be, given a label\n",
    "# (c) Tariq Rashid, 2016\n",
    "# license is GPLv2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy\n",
    "# scipy.special for the sigmoid function expit(), and its inverse logit()\n",
    "import scipy.special\n",
    "# library for plotting arrays\n",
    "import matplotlib.pyplot\n",
    "# ensure the plots are inside this notebook, not an external window\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# neural network class definition\n",
    "class neuralNetwork:\n",
    "    \n",
    "    \n",
    "    # initialise the neural network\n",
    "    def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):\n",
    "        # set number of nodes in each input, hidden, output layer\n",
    "        self.inodes = inputnodes\n",
    "        self.hnodes = hiddennodes\n",
    "        self.onodes = outputnodes\n",
    "        \n",
    "        # link weight matrices, wih and who\n",
    "        # weights inside the arrays are w_i_j, where link is from node i to node j in the next layer\n",
    "        # w11 w21\n",
    "        # w12 w22 etc \n",
    "        self.wih = numpy.random.normal(0.0, pow(self.inodes, -0.5), (self.hnodes, self.inodes))\n",
    "        self.who = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.onodes, self.hnodes))\n",
    "\n",
    "        # learning rate\n",
    "        self.lr = learningrate\n",
    "        \n",
    "        # activation function is the sigmoid function\n",
    "        self.activation_function = lambda x: scipy.special.expit(x)\n",
    "        self.inverse_activation_function = lambda x: scipy.special.logit(x)\n",
    "        \n",
    "        pass\n",
    "\n",
    "    \n",
    "    # train the neural network\n",
    "    def train(self, inputs_list, targets_list):\n",
    "        # convert inputs list to 2d array\n",
    "        inputs = numpy.array(inputs_list, ndmin=2).T\n",
    "        targets = numpy.array(targets_list, ndmin=2).T\n",
    "        \n",
    "        # calculate signals into hidden layer\n",
    "        hidden_inputs = numpy.dot(self.wih, inputs)\n",
    "        # calculate the signals emerging from hidden layer\n",
    "        hidden_outputs = self.activation_function(hidden_inputs)\n",
    "        \n",
    "        # calculate signals into final output layer\n",
    "        final_inputs = numpy.dot(self.who, hidden_outputs)\n",
    "        # calculate the signals emerging from final output layer\n",
    "        final_outputs = self.activation_function(final_inputs)\n",
    "        \n",
    "        # output layer error is the (target - actual)\n",
    "        output_errors = targets - final_outputs\n",
    "        # hidden layer error is the output_errors, split by weights, recombined at hidden nodes\n",
    "        hidden_errors = numpy.dot(self.who.T, output_errors) \n",
    "        \n",
    "        # update the weights for the links between the hidden and output layers\n",
    "        self.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)), numpy.transpose(hidden_outputs))\n",
    "        \n",
    "        # update the weights for the links between the input and hidden layers\n",
    "        self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))\n",
    "        \n",
    "        pass\n",
    "\n",
    "    \n",
    "    # query the neural network\n",
    "    def query(self, inputs_list):\n",
    "        # convert inputs list to 2d array\n",
    "        inputs = numpy.array(inputs_list, ndmin=2).T\n",
    "        \n",
    "        # calculate signals into hidden layer\n",
    "        hidden_inputs = numpy.dot(self.wih, inputs)\n",
    "        # calculate the signals emerging from hidden layer\n",
    "        hidden_outputs = self.activation_function(hidden_inputs)\n",
    "        \n",
    "        # calculate signals into final output layer\n",
    "        final_inputs = numpy.dot(self.who, hidden_outputs)\n",
    "        # calculate the signals emerging from final output layer\n",
    "        final_outputs = self.activation_function(final_inputs)\n",
    "        \n",
    "        return final_outputs\n",
    "    \n",
    "    \n",
    "    # backquery the neural network\n",
    "    # we'll use the same termnimology to each item, \n",
    "    # eg target are the values at the right of the network, albeit used as input\n",
    "    # eg hidden_output is the signal to the right of the middle nodes\n",
    "    def backquery(self, targets_list):\n",
    "        # transpose the targets list to a vertical array\n",
    "        final_outputs = numpy.array(targets_list, ndmin=2).T\n",
    "        \n",
    "        # calculate the signal into the final output layer\n",
    "        final_inputs = self.inverse_activation_function(final_outputs)\n",
    "\n",
    "        # calculate the signal out of the hidden layer\n",
    "        hidden_outputs = numpy.dot(self.who.T, final_inputs)\n",
    "        # scale them back to 0.01 to .99\n",
    "        hidden_outputs -= numpy.min(hidden_outputs)\n",
    "        hidden_outputs /= numpy.max(hidden_outputs)\n",
    "        hidden_outputs *= 0.98\n",
    "        hidden_outputs += 0.01\n",
    "        \n",
    "        # calculate the signal into the hidden layer\n",
    "        hidden_inputs = self.inverse_activation_function(hidden_outputs)\n",
    "        \n",
    "        # calculate the signal out of the input layer\n",
    "        inputs = numpy.dot(self.wih.T, hidden_inputs)\n",
    "        # scale them back to 0.01 to .99\n",
    "        inputs -= numpy.min(inputs)\n",
    "        inputs /= numpy.max(inputs)\n",
    "        inputs *= 0.98\n",
    "        inputs += 0.01\n",
    "        \n",
    "        return inputs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# number of input, hidden and output nodes\n",
    "input_nodes = 784\n",
    "hidden_nodes = 200\n",
    "output_nodes = 10\n",
    "\n",
    "# learning rate\n",
    "learning_rate = 0.1\n",
    "\n",
    "# create instance of neural network\n",
    "n = neuralNetwork(input_nodes,hidden_nodes,output_nodes, learning_rate)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# load the mnist training data CSV file into a list\n",
    "training_data_file = open(\"mnist_dataset/mnist_train.csv\", 'r')\n",
    "training_data_list = training_data_file.readlines()\n",
    "training_data_file.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# train the neural network\n",
    "\n",
    "# epochs is the number of times the training data set is used for training\n",
    "epochs = 5\n",
    "\n",
    "for e in range(epochs):\n",
    "    # go through all records in the training data set\n",
    "    for record in training_data_list:\n",
    "        # split the record by the ',' commas\n",
    "        all_values = record.split(',')\n",
    "        # scale and shift the inputs\n",
    "        inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01\n",
    "        # create the target output values (all 0.01, except the desired label which is 0.99)\n",
    "        targets = numpy.zeros(output_nodes) + 0.01\n",
    "        # all_values[0] is the target label for this record\n",
    "        targets[int(all_values[0])] = 0.99\n",
    "        n.train(inputs, targets)\n",
    "        pass\n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# load the mnist test data CSV file into a list\n",
    "test_data_file = open(\"mnist_dataset/mnist_test.csv\", 'r')\n",
    "test_data_list = test_data_file.readlines()\n",
    "test_data_file.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# test the neural network\n",
    "\n",
    "# scorecard for how well the network performs, initially empty\n",
    "scorecard = []\n",
    "\n",
    "# go through all the records in the test data set\n",
    "for record in test_data_list:\n",
    "    # split the record by the ',' commas\n",
    "    all_values = record.split(',')\n",
    "    # correct answer is first value\n",
    "    correct_label = int(all_values[0])\n",
    "    # scale and shift the inputs\n",
    "    inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01\n",
    "    # query the network\n",
    "    outputs = n.query(inputs)\n",
    "    # the index of the highest value corresponds to the label\n",
    "    label = numpy.argmax(outputs)\n",
    "    # append correct or incorrect to list\n",
    "    if (label == correct_label):\n",
    "        # network's answer matches correct answer, add 1 to scorecard\n",
    "        scorecard.append(1)\n",
    "    else:\n",
    "        # network's answer doesn't match correct answer, add 0 to scorecard\n",
    "        scorecard.append(0)\n",
    "        pass\n",
    "    \n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "performance =  0.9733\n"
     ]
    }
   ],
   "source": [
    "# calculate the performance score, the fraction of correct answers\n",
    "scorecard_array = numpy.asarray(scorecard)\n",
    "print (\"performance = \", scorecard_array.sum() / scorecard_array.size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0.99  0.01  0.01  0.01  0.01  0.01  0.01  0.01  0.01  0.01]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f6c84ea16a0>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\naCgMI17JnQAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f6c88503cf8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# run the network backwards, given a label, see what image it produces\n",
    "\n",
    "# label to test\n",
    "label = 0\n",
    "# create the output signals for this label\n",
    "targets = numpy.zeros(output_nodes) + 0.01\n",
    "# all_values[0] is the target label for this record\n",
    "targets[label] = 0.99\n",
    "print(targets)\n",
    "\n",
    "# get image data\n",
    "image_data = n.backquery(targets)\n",
    "\n",
    "# plot image data\n",
    "matplotlib.pyplot.imshow(image_data.reshape(28,28), cmap='Greys', interpolation='None')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
